/******************************************************************************
秋夜静，独坐对残灯。
啼笑非非谁识我，坐行梦梦尽缘君，何所慰消沉。
风卷雨，雨复卷侬心。
心似欲随风雨去，茫茫大海任浮沉。
无爱亦无恨。
******************************************************************************/
#include "RGB_Slave.h"

//const uint8_t rgb_slave_head[RGB_SLAVE_CMD_TEST+2][3] = {
//    {RGB_SLAVE_HEAD, RGB_SLAVE_CMD_ACK,    6},
//    {RGB_SLAVE_HEAD, RGB_SLAVE_CMD_SLEEP,  3},
//    {RGB_SLAVE_HEAD, RGB_SLAVE_CMD_INIT,   66},
//    {RGB_SLAVE_HEAD, RGB_SLAVE_CMD_CTRL,   39},
//    {RGB_SLAVE_HEAD, RGB_SLAVE_CMD_UDEF,   129},
//    {RGB_SLAVE_HEAD, RGB_SLAVE_CMD_RECORD, 129},
//    {RGB_SLAVE_HEAD, RGB_SLAVE_CMD_DIRECT, 381},
//    {RGB_SLAVE_HEAD, RGB_SLAVE_CMD_READ,   3},
//    {RGB_SLAVE_HEAD, RGB_SLAVE_CMD_TEST,   38},
//};

/*
数据包格式
| 0x5C | 0xFF|  1B  |  1B  |  1B   |~0x5C| 6B
| head | cmd | _cmd | code | check | end |
*/
int rgb_slave_ack(uint8_t buf[384], const uint8_t _cmd, const uint8_t code, const uint8_t check)
{
    int index=0;
    buf[index++] = RGB_SLAVE_HEAD;
    buf[index++] = RGB_SLAVE_CMD_ACK;
    buf[index++] = _cmd;
    buf[index++] = code;
    buf[index++] = check;
    buf[index++] = ~RGB_SLAVE_HEAD; // end
    return index;
}
int rgb_slave_ack_decode(const uint8_t buf[], const uint16_t len, struct RGB_Slave_ack *const ack)
{
    int index=0;
    uint8_t head, cmd;
    head = buf[index++];
    if(RGB_SLAVE_HEAD!=head) return -1;
    cmd = buf[index++];
    if(RGB_SLAVE_CMD_ACK!=cmd) return -2;
    ack->_cmd = buf[index++];
    ack->code = buf[index++];
    ack->check = buf[index++];
    if(((~RGB_SLAVE_HEAD)&0xFF)!= buf[index++] ) return -2;
    if(index>len) return -3;  // over
    return index;
}
/*
数据包格式
| 0x5C | 0x00|~0x5C| 3B
| head | cmd | end |
*/
int rgb_slave_sleep(uint8_t buf[384])
{
    int index=0;
    buf[index++] = RGB_SLAVE_HEAD;
    buf[index++] = RGB_SLAVE_CMD_SLEEP;
    buf[index++] = ~RGB_SLAVE_HEAD; // end
    return index;
}
/*
数据包格式
| 0x5C | 0x01|  21  |  6   |  1B    |  1B  |  4B  |  24B |   32B   |~0x5C| 67B
| head | cmd | cols | rows | IdxLogo| RevX | RevY | masks| palettes| end |
*/
int rgb_slave_init(uint8_t buf[384], const uint8_t cols, const uint8_t rows, const uint8_t IdxLogo, const uint8_t reverseX, const uint32_t reverseY, const uint32_t masks[RGB_SLAVE_KB_ROWS], const uint32_t palettes[8])
{
    int index=0;
    uint32_t data;
    uint8_t cnt=0;
    buf[index++] = RGB_SLAVE_HEAD;
    buf[index++] = RGB_SLAVE_CMD_INIT;
    buf[index++] = cols;
    buf[index++] = rows;
    buf[index++] = IdxLogo;
    buf[index++] = reverseX;
    buf[index++] = (reverseY>>0)&0xFF;
    buf[index++] = (reverseY>>8)&0xFF;
    buf[index++] = (reverseY>>16)&0xFF;
    buf[index++] = (reverseY>>24)&0xFF;
    for(cnt=0; cnt<RGB_SLAVE_KB_ROWS; cnt++)
    {
        data = masks[cnt];
        buf[index++] = (data>>0)&0xFF;
        buf[index++] = (data>>8)&0xFF;
        buf[index++] = (data>>16)&0xFF;
        buf[index++] = (data>>24)&0xFF;
    }
    for(cnt=0; cnt<8; cnt++)
    {
        data = palettes[cnt];
        buf[index++] = (data>>0)&0xFF;
        buf[index++] = (data>>8)&0xFF;
        buf[index++] = (data>>16)&0xFF;
        buf[index++] = (data>>24)&0xFF;
    }
    buf[index++] = ~RGB_SLAVE_HEAD; // end
    return index;
}
int rgb_slave_init_decode(const uint8_t buf[], const uint16_t len, struct RGB_Slave_init *const init)
{
    int index=0;
    uint32_t data;
    uint16_t cnt=0;
    uint8_t head, cmd;
    head = buf[index++];
    if(RGB_SLAVE_HEAD!=head) return -1;
    cmd = buf[index++];
    if(RGB_SLAVE_CMD_INIT!=cmd) return -2;
    init->cols = buf[index++];
    init->rows = buf[index++];
    init->IdxLogo = buf[index++];
    init->reverseX = buf[index++];
    data = (buf[index++]&0xFF);//<<0;
    data = data | (buf[index++]&0xFF)<<8;
    data = data | (buf[index++]&0xFF)<<16;
    data = data | (buf[index++]&0xFF)<<24;
    init->reverseY = data;
    for(cnt=0; cnt<RGB_SLAVE_KB_ROWS; cnt++)
    {
        data = (buf[index++]&0xFF);//<<0;
        data = data | (buf[index++]&0xFF)<<8;
        data = data | (buf[index++]&0xFF)<<16;
        data = data | (buf[index++]&0xFF)<<24;
        init->masks[cnt] = data;
    }
    for(cnt=0; cnt<RGB_SLAVE_PALETTE; cnt++)
    {
        data = (buf[index++]&0xFF);//<<0;
        data = data | (buf[index++]&0xFF)<<8;
        data = data | (buf[index++]&0xFF)<<16;
        data = data | (buf[index++]&0xFF)<<24;
        init->palettes[cnt] = data;
    }
    if(((~RGB_SLAVE_HEAD)&0xFF)!= buf[index++] ) return -2;
    if(index>len) return -3;  // over
    return index;
}
/*
数据包格式
| 0x5C | 0x02|  1B  |  1B   | 1B  | 1B  |  4B  |  4B  |  24B |  1B  |~0x5C| 40B
| head | cmd | Mode | Speed | Rev | Gray| back | logo | keys | norm | end |
*/
int rgb_slave_ctrl(uint8_t buf[384], const uint8_t IdxMode, const uint8_t Speed, const uint8_t reverse, const uint8_t Grayscale, const uint32_t background, const uint32_t logo, const uint32_t keys[RGB_SLAVE_KB_ROWS], const uint8_t normally)
{
    int index=0;
    uint32_t key;
    uint8_t cnt=0;
    buf[index++] = RGB_SLAVE_HEAD;
    buf[index++] = RGB_SLAVE_CMD_CTRL;
    buf[index++] = IdxMode;
    buf[index++] = Speed;
    buf[index++] = reverse;
    buf[index++] = Grayscale;
    // background
    buf[index++] = (background>>0)&0xFF;
    buf[index++] = (background>>8)&0xFF;
    buf[index++] = (background>>16)&0xFF;
    buf[index++] = (background>>24)&0xFF;
    buf[index++] = (logo>>0)&0xFF;
    buf[index++] = (logo>>8)&0xFF;
    buf[index++] = (logo>>16)&0xFF;
    buf[index++] = (logo>>24)&0xFF;
    for(cnt=0; cnt<RGB_SLAVE_KB_ROWS; cnt++)
    {
        key = keys[cnt];
        buf[index++] = (key>>0)&0xFF;
        buf[index++] = (key>>8)&0xFF;
        buf[index++] = (key>>16)&0xFF;
        buf[index++] = (key>>24)&0xFF;
    }
    buf[index++] = normally;
    buf[index++] = ~RGB_SLAVE_HEAD; // end
    return index;
}
int rgb_slave_ctrl_decode(const uint8_t buf[], const uint16_t len, struct RGB_Slave_control *const ctrl)
{
    int index=0;
    uint32_t data;
    uint16_t cnt=0;
    uint8_t head, cmd;
    head = buf[index++];
    if(RGB_SLAVE_HEAD!=head) return -1;
    cmd = buf[index++];
    if(RGB_SLAVE_CMD_CTRL!=cmd) return -2;
    ctrl->IdxMode = buf[index++];
    ctrl->Speed = buf[index++];
    ctrl->reverse = buf[index++];
    ctrl->Grayscale = buf[index++];
    {
        data = (buf[index++]&0xFF);//<<0;
        data = data | (buf[index++]&0xFF)<<8;
        data = data | (buf[index++]&0xFF)<<16;
        data = data | (buf[index++]&0xFF)<<24;
        ctrl->background = data;
        data = (buf[index++]&0xFF);//<<0;
        data = data | (buf[index++]&0xFF)<<8;
        data = data | (buf[index++]&0xFF)<<16;
        data = data | (buf[index++]&0xFF)<<24;
        ctrl->logo = data;
    }
    for(cnt=0; cnt<RGB_SLAVE_KB_ROWS; cnt++)
    {
        data = (buf[index++]&0xFF);//<<0;
        data = data | (buf[index++]&0xFF)<<8;
        data = data | (buf[index++]&0xFF)<<16;
        data = data | (buf[index++]&0xFF)<<24;
        ctrl->keys[cnt] = data;
    }
    ctrl->normally = buf[index++];
    if(((~RGB_SLAVE_HEAD)&0xFF)!= buf[index++] ) return -2;
    if(index>len) return -3;  // over
    return index;
}
/*
数据包格式
| 0x5C | 0x03|126B |~0x5C| 129B
| head | cmd | rgb | end |
0x03:自定义(调色板中颜色索引0-6);
0x04:自定义录制(调色板中颜色索引0-6);
*/
int rgb_slave_udef(uint8_t buf[384], const uint8_t IdxRGB[RGB_SLAVE_KB_ROWS*RGB_SLAVE_KB_COLS])
{
    int index=0;
    uint8_t cnt=0;
    buf[index++] = RGB_SLAVE_HEAD;
    buf[index++] = RGB_SLAVE_CMD_UDEF;
    //buf[index++] = offset;
    for(cnt=0; cnt<(RGB_SLAVE_KB_ROWS*RGB_SLAVE_KB_COLS); cnt++)
    {
        buf[index++] = IdxRGB[cnt];
    }
    buf[index++] = ~RGB_SLAVE_HEAD; // end
    return index;
}
int rgb_slave_record(uint8_t buf[384], const uint8_t IdxRGB[RGB_SLAVE_KB_ROWS*RGB_SLAVE_KB_COLS])
{
    int index=0;
    uint8_t cnt=0;
    buf[index++] = RGB_SLAVE_HEAD;
    buf[index++] = RGB_SLAVE_CMD_RECORD;
    //buf[index++] = offset;
    for(cnt=0; cnt<(RGB_SLAVE_KB_ROWS*RGB_SLAVE_KB_COLS); cnt++)
    {
        buf[index++] = IdxRGB[cnt];
    }
    buf[index++] = ~RGB_SLAVE_HEAD; // end
    return index;
}
/*
数据包格式
| 0x5C | 0x05|126B |~0x5C| 129B
| head | cmd | rgb | end |
*/
int rgb_slave_direct(uint8_t buf[384], const uint32_t rgb[RGB_SLAVE_KB_ROWS*RGB_SLAVE_KB_COLS])
{
    int index=0;
    uint32_t color;
    uint8_t cnt=0;
    buf[index++] = RGB_SLAVE_HEAD;
    buf[index++] = RGB_SLAVE_CMD_DIRECT;
    //buf[index++] = offset;
    for(cnt=0; cnt<(RGB_SLAVE_KB_ROWS*RGB_SLAVE_KB_COLS); cnt++)//for(cnt=0; cnt<(RGB_SLAVE_KB_ROWS/3*RGB_SLAVE_KB_COLS); cnt++)
    {
        color = rgb[cnt];
        buf[index++] = (color>>0)&0xFF;
        buf[index++] = (color>>8)&0xFF;
        buf[index++] = (color>>16)&0xFF;
    }
    buf[index++] = ~RGB_SLAVE_HEAD; // end
    return index;
}
int rgb_slave_direct_sub(uint8_t buf[384], const uint8_t direct, const uint32_t rgb[RGB_SLAVE_KB_ROWS/3*RGB_SLAVE_KB_COLS])
{
    int index=0;
    uint32_t color;
    uint8_t cnt=0;
    uint8_t offset=0;
    buf[index++] = RGB_SLAVE_HEAD;
    buf[index++] = direct;//RGB_SLAVE_CMD_DIRECT;
    if(RGB_SLAVE_CMD_DIRECT2==direct) offset=2*RGB_SLAVE_KB_COLS;
    if(RGB_SLAVE_CMD_DIRECT3==direct) offset=4*RGB_SLAVE_KB_COLS;
    //buf[index++] = offset;
    for(cnt=0; cnt<(RGB_SLAVE_KB_ROWS*RGB_SLAVE_KB_COLS)/3; cnt++)
    {
        color = rgb[cnt+offset];
        buf[index++] = (color>>0)&0xFF;
        buf[index++] = (color>>8)&0xFF;
        buf[index++] = (color>>16)&0xFF;
    }
    buf[index++] = ~RGB_SLAVE_HEAD; // end
    return index;
}
/*
数据包格式
| 0x5C | 0x06|~0x5C| 4B
| head | cmd | end |
*/
int rgb_slave_read(uint8_t buf[384]/*, const uint8_t offset*/)
{
    int index=0;
    buf[index++] = RGB_SLAVE_HEAD;
    buf[index++] = RGB_SLAVE_CMD_READ;
    //buf[index++] = offset;
    buf[index++] = ~RGB_SLAVE_HEAD; // end
    return index;
}
/*
数据包格式
| 0x5C | 0x07|  1B |  1B |  1B    |  1B  |  4B  |  24B |  4B   |~0x5C| 39B
| head | cmd | col | row | IdxLogo| RevX | RevY | masks| color | end |
*/
int rgb_slave_test(uint8_t buf[384], const uint8_t col, const uint8_t row, const uint8_t IdxLogo, const uint8_t reverseX, const uint32_t reverseY, const uint32_t masks[RGB_SLAVE_KB_ROWS], const uint32_t color)
{
    int index=0;
    uint32_t mask;
    uint8_t cnt=0;
    buf[index++] = RGB_SLAVE_HEAD;
    buf[index++] = RGB_SLAVE_CMD_TEST;
    buf[index++] = col;
    buf[index++] = row;
    buf[index++] = IdxLogo;
    buf[index++] = reverseX;
    buf[index++] = (reverseY>>0)&0xFF;
    buf[index++] = (reverseY>>8)&0xFF;
    buf[index++] = (reverseY>>16)&0xFF;
    buf[index++] = (reverseY>>24)&0xFF;
    for(cnt=0; cnt<RGB_SLAVE_KB_ROWS; cnt++)
    {
        mask = masks[cnt];
        buf[index++] = (mask>>0)&0xFF;
        buf[index++] = (mask>>8)&0xFF;
        buf[index++] = (mask>>16)&0xFF;
        buf[index++] = (mask>>24)&0xFF;
    }
    buf[index++] = (color>>0)&0xFF;
    buf[index++] = (color>>8)&0xFF;
    buf[index++] = (color>>16)&0xFF;
    buf[index++] = (color>>24)&0xFF;
    buf[index++] = ~RGB_SLAVE_HEAD; // end
    return index;
}
int rgb_slave_test_decode(const uint8_t buf[], const uint16_t len, struct RGB_Slave_test *const test)
{
    int index=0;
    uint32_t data;
    uint16_t cnt=0;
    uint8_t head, cmd;
    head = buf[index++];
    if(RGB_SLAVE_HEAD!=head) return -1;
    cmd = buf[index++];
    if(RGB_SLAVE_CMD_TEST!=cmd) return -2;
    test->col = buf[index++];
    test->row = buf[index++];
    test->IdxLogo = buf[index++];
    test->reverseX = buf[index++];
    data = (buf[index++]&0xFF);//<<0;
    data = data | (buf[index++]&0xFF)<<8;
    data = data | (buf[index++]&0xFF)<<16;
    data = data | (buf[index++]&0xFF)<<24;
    test->reverseY = data;
    for(cnt=0; cnt<RGB_SLAVE_KB_ROWS; cnt++)
    {
        data = (buf[index++]&0xFF);//<<0;
        data = data | (buf[index++]&0xFF)<<8;
        data = data | (buf[index++]&0xFF)<<16;
        data = data | (buf[index++]&0xFF)<<24;
        test->masks[cnt] = data;
    }
    {
        data = (buf[index++]&0xFF);//<<0;
        data = data | (buf[index++]&0xFF)<<8;
        data = data | (buf[index++]&0xFF)<<16;
        data = data | (buf[index++]&0xFF)<<24;
        test->color = data;
    }
    if(((~RGB_SLAVE_HEAD)&0xFF)!= buf[index++] ) return -2;
    if(index>len) return -3;  // over
    return index;
}

// 通用编码函数,对数据进行编码,并返回编码后的数据长度
int rgb_slave_encode(uint8_t buf[384], union RGB_Slave_t *slave)
{
	int index=0;
    uint32_t data;
    uint16_t cnt=0;
	buf[index++] = RGB_SLAVE_HEAD;
	buf[index++] = slave->cmd;
	switch(slave->cmd)
	{
		case RGB_SLAVE_CMD_ACK:
		/*
		数据包格式
		| 0x5C | 0xFF|  1B  |  1B  |  1B   |~0x5C| 6B
		| head | cmd | _cmd | code | check | end |
		*/
			buf[index++] = slave->ack._cmd;
			buf[index++] = slave->ack.code;
			buf[index++] = slave->ack.check;
			break;
		case RGB_SLAVE_CMD_SLEEP:
			break;
		case RGB_SLAVE_CMD_INIT:
        /*
        数据包格式
        | 0x5C | 0x01|  21  |  6   |  1B    |  1B  |  4B  |  24B |   32B   |~0x5C| 67B
        | head | cmd | cols | rows | IdxLogo| RevX | RevY | masks| palettes| end |
        */
			buf[index++] = slave->init.cols;
			buf[index++] = slave->init.rows;
            buf[index++] = slave->init.IdxLogo;
            buf[index++] = slave->init.reverseX;
            buf[index++] = (slave->init.reverseY>>0)&0xFF;
            buf[index++] = (slave->init.reverseY>>8)&0xFF;
            buf[index++] = (slave->init.reverseY>>16)&0xFF;
            buf[index++] = (slave->init.reverseY>>24)&0xFF;
            for(cnt=0; cnt<RGB_SLAVE_KB_ROWS; cnt++)
            {
                data = slave->init.masks[cnt];
                buf[index++] = (data>>0)&0xFF;
                buf[index++] = (data>>8)&0xFF;
                buf[index++] = (data>>16)&0xFF;
                buf[index++] = (data>>24)&0xFF;
            }
            for(cnt=0; cnt<RGB_SLAVE_PALETTE; cnt++)
            {
                data = slave->init.palettes[cnt];
                buf[index++] = (data>>0)&0xFF;
                buf[index++] = (data>>8)&0xFF;
                buf[index++] = (data>>16)&0xFF;
                buf[index++] = (data>>24)&0xFF;
            }
			break;
		case RGB_SLAVE_CMD_CTRL:
		/*
		数据包格式
		| 0x5C | 0x02|  1B  |  1B   | 1B  |  3B  |  18B |  1B  |~0x5C| 28B
		| head | cmd | Mode | Speed | Rev | back | keys | norm | end |
		*/
			buf[index++] = slave->control.IdxMode;
			buf[index++] = slave->control.Speed;
			buf[index++] = slave->control.reverse;
            buf[index++] = slave->control.Grayscale;
            {
                data = slave->control.background;
                buf[index++] = (data>>0)&0xFF;
                buf[index++] = (data>>8)&0xFF;
                buf[index++] = (data>>16)&0xFF;
                buf[index++] = (data>>24)&0xFF;
                data = slave->control.logo;
                buf[index++] = (data>>0)&0xFF;
                buf[index++] = (data>>8)&0xFF;
                buf[index++] = (data>>16)&0xFF;
                buf[index++] = (data>>24)&0xFF;
            }
            for(cnt=0; cnt<RGB_SLAVE_KB_ROWS; cnt++)
            {
                data = slave->control.keys[cnt];
                buf[index++] = (data>>0)&0xFF;
                buf[index++] = (data>>8)&0xFF;
                buf[index++] = (data>>16)&0xFF;
                buf[index++] = (data>>24)&0xFF;
            }
			buf[index++] = slave->control.normally;
			break;
		case RGB_SLAVE_CMD_UDEF:
		case RGB_SLAVE_CMD_RECORD:
        /*
        数据包格式
        | 0x5C | 0x03|126B |~0x5C| 129B
        | head | cmd | rgb | end |
        0x03:自定义(调色板中颜色索引0-6);
        0x04:自定义录制(调色板中颜色索引0-6);
        */
            //buf[index++] = slave->transfer.offset;
            for(cnt=0; cnt<sizeof(slave->transfer_rgb); cnt++) buf[index++] = slave->transfer_rgb[cnt];
			break;
        case RGB_SLAVE_CMD_DIRECT:  // 直驱
        /*
        数据包格式
        | 0x5C | 0x05|378B |~0x5C| 381B
        | head | cmd | rgb | end |
        */
            //buf[index++] = slave->transfer.offset;
            //for(cnt=0; cnt<sizeof(slave->direct.rgb); cnt++) buf[index++] = slave->direct.rgb[cnt];
            for(cnt=0; cnt<(RGB_SLAVE_KB_ROWS*RGB_SLAVE_KB_COLS); cnt++)
            {
                data = slave->direct_rgb[cnt];
                buf[index++] = (data>>0)&0xFF;
                buf[index++] = (data>>8)&0xFF;
                buf[index++] = (data>>16)&0xFF;
            }
            break;
        case RGB_SLAVE_CMD_DIRECT1:  // 直驱
        /*
        数据包格式
        | 0x5C | 0x05|126B |~0x5C| 129B
        | head | cmd | rgb | end |
        */
            //buf[index++] = slave->transfer.offset;
            //for(cnt=0; cnt<sizeof(slave->direct_sub.rgb); cnt++) buf[index++] = slave->direct_sub.rgb[cnt];
            for(cnt=0; cnt<(RGB_SLAVE_KB_ROWS*RGB_SLAVE_KB_COLS/3); cnt++)
            {
                data = slave->direct_rgb[cnt];
                buf[index++] = (data>>0)&0xFF;
                buf[index++] = (data>>8)&0xFF;
                buf[index++] = (data>>16)&0xFF;
            }
            break;
        case RGB_SLAVE_CMD_DIRECT2:  // 直驱
        /*
        数据包格式
        | 0x5C | 0x05|126B |~0x5C| 129B
        | head | cmd | rgb | end |
        */
            //buf[index++] = slave->transfer.offset;
            //for(cnt=0; cnt<sizeof(slave->direct_sub.rgb); cnt++) buf[index++] = slave->direct_sub.rgb[cnt];
            for(cnt=0; cnt<(RGB_SLAVE_KB_ROWS*RGB_SLAVE_KB_COLS/3); cnt++)
            {
                data = slave->direct_rgb[cnt+2*RGB_SLAVE_KB_COLS];
                buf[index++] = (data>>0)&0xFF;
                buf[index++] = (data>>8)&0xFF;
                buf[index++] = (data>>16)&0xFF;
            }
            break;
        case RGB_SLAVE_CMD_DIRECT3:  // 直驱
        /*
        数据包格式
        | 0x5C | 0x05|126B |~0x5C| 129B
        | head | cmd | rgb | end |
        */
            //buf[index++] = slave->transfer.offset;
            //for(cnt=0; cnt<sizeof(slave->direct_sub.rgb); cnt++) buf[index++] = slave->direct_sub.rgb[cnt];
            for(cnt=0; cnt<(RGB_SLAVE_KB_ROWS*RGB_SLAVE_KB_COLS/3); cnt++)
            {
                data = slave->direct_rgb[cnt+4*RGB_SLAVE_KB_COLS];
                buf[index++] = (data>>0)&0xFF;
                buf[index++] = (data>>8)&0xFF;
                buf[index++] = (data>>16)&0xFF;
            }
            break;
		case RGB_SLAVE_CMD_READ:
            //buf[index++] = slave->read.offset;
			break;
        case RGB_SLAVE_CMD_TEST:
        /*
        数据包格式
        | 0x5C | 0x07|  1B |  1B |  1B    |  1B  |  4B  |  24B |  4B   |~0x5C| 39B
        | head | cmd | col | row | IdxLogo| RevX | RevY | masks| color | end |
        */
            buf[index++] = slave->test.col;
            buf[index++] = slave->test.row;
            buf[index++] = slave->test.IdxLogo;
            buf[index++] = slave->test.reverseX;
            buf[index++] = (slave->test.reverseY>>0)&0xFF;
            buf[index++] = (slave->test.reverseY>>8)&0xFF;
            buf[index++] = (slave->test.reverseY>>16)&0xFF;
            buf[index++] = (slave->test.reverseY>>24)&0xFF;
            for(cnt=0; cnt<RGB_SLAVE_KB_ROWS; cnt++)
            {
                data = slave->test.masks[cnt];
                buf[index++] = (data>>0)&0xFF;
                buf[index++] = (data>>8)&0xFF;
                buf[index++] = (data>>16)&0xFF;
                buf[index++] = (data>>24)&0xFF;
            }
            {
                data = slave->test.color;
                buf[index++] = (data>>0)&0xFF;
                buf[index++] = (data>>8)&0xFF;
                buf[index++] = (data>>16)&0xFF;
                buf[index++] = (data>>24)&0xFF;
            }
            break;
		default:
			return -1;  // 错误
	}
	buf[index++] = ~RGB_SLAVE_HEAD; // end
	return index;
}
// 通用解码函数,对数据进行解码,并返回解码的数据长度
int rgb_slave_decode(const uint8_t buf[384], const uint16_t len, union RGB_Slave_t *slave)
{
	int index=0;
    uint32_t data;
    uint16_t cnt=0;
	if(RGB_SLAVE_HEAD!=buf[index]) return -1;
	slave->head = buf[index++];
	slave->cmd = buf[index++];
	switch(slave->cmd)
	{
		case RGB_SLAVE_CMD_ACK:
		/*
		数据包格式
		| 0x5C | 0xFF|  1B  |  1B  |  1B   |~0x5C| 6B
		| head | cmd | _cmd | code | check | end |
		*/
			slave->ack._cmd = buf[index++];
			slave->ack.code = buf[index++];
			slave->ack.check = buf[index++];
			break;
		case RGB_SLAVE_CMD_SLEEP:
			break;
		case RGB_SLAVE_CMD_INIT:
        /*
        数据包格式
        | 0x5C | 0x01|  21  |  6   |  1B    |  1B  |  4B  |  24B |   32B   |~0x5C| 67B
        | head | cmd | cols | rows | IdxLogo| RevX | RevY | masks| palettes| end |
        */
			slave->init.cols = buf[index++];
			slave->init.rows = buf[index++];
            slave->init.IdxLogo = buf[index++];
            slave->init.reverseX = buf[index++];
            data = (buf[index++]&0xFF);//<<0;
            data = data | (buf[index++]&0xFF)<<8;
            data = data | (buf[index++]&0xFF)<<16;
            data = data | (buf[index++]&0xFF)<<24;
            slave->init.reverseY = data;
            for(cnt=0; cnt<RGB_SLAVE_KB_ROWS; cnt++)
            {
                data = (buf[index++]&0xFF);//<<0;
                data = data | (buf[index++]&0xFF)<<8;
                data = data | (buf[index++]&0xFF)<<16;
                data = data | (buf[index++]&0xFF)<<24;
                slave->init.masks[cnt] = data;
            }
            for(cnt=0; cnt<RGB_SLAVE_PALETTE; cnt++)
            {
                data = (buf[index++]&0xFF);//<<0;
                data = data | (buf[index++]&0xFF)<<8;
                data = data | (buf[index++]&0xFF)<<16;
                data = data | (buf[index++]&0xFF)<<24;
                slave->init.palettes[cnt] = data;
            }
			break;
		case RGB_SLAVE_CMD_CTRL:
        /*
        数据包格式
        | 0x5C | 0x02|  1B  |  1B   | 1B  |  4B  |  4B  |  24B |  1B  |~0x5C| 39B
        | head | cmd | Mode | Speed | Rev | back | logo | keys | norm | end |
        */
			slave->control.IdxMode = buf[index++];
			slave->control.Speed = buf[index++];
			slave->control.reverse = buf[index++];
            slave->control.Grayscale = buf[index++];
            {
                data = (buf[index++]&0xFF);//<<0;
                data = data | (buf[index++]&0xFF)<<8;
                data = data | (buf[index++]&0xFF)<<16;
                data = data | (buf[index++]&0xFF)<<24;
                slave->control.background = data;
                data = (buf[index++]&0xFF);//<<0;
                data = data | (buf[index++]&0xFF)<<8;
                data = data | (buf[index++]&0xFF)<<16;
                data = data | (buf[index++]&0xFF)<<24;
                slave->control.logo = data;
            }
            for(cnt=0; cnt<RGB_SLAVE_KB_ROWS; cnt++)
            {
                data = (buf[index++]&0xFF);//<<0;
                data = data | (buf[index++]&0xFF)<<8;
                data = data | (buf[index++]&0xFF)<<16;
                data = data | (buf[index++]&0xFF)<<24;
                slave->control.keys[cnt] = data;
            }
			slave->control.normally = buf[index++];
			break;
		case RGB_SLAVE_CMD_UDEF:
		case RGB_SLAVE_CMD_RECORD:
        /*
        数据包格式
        | 0x5C | 0x03|126B |~0x5C| 129B
        | head | cmd | rgb | end |
        0x03:自定义(调色板中颜色索引0-6);
        0x04:自定义录制(调色板中颜色索引0-6);
        */
            //slave->transfer.offset = buf[index++];
            for(cnt=0; cnt<sizeof(slave->transfer_rgb); cnt++) slave->transfer_rgb[cnt] = buf[index++];
			break;
        case RGB_SLAVE_CMD_DIRECT:   // 直驱
        /*
        数据包格式
        | 0x5C | 0x05|378B |~0x5C| 381B
        | head | cmd | rgb | end |
        */
            //slave->transfer.offset = buf[index++];
            //for(cnt=0; cnt<sizeof(slave->direct.rgb); cnt++) slave->direct.rgb[cnt] = buf[index++];
            for(cnt=0; cnt<(RGB_SLAVE_KB_ROWS*RGB_SLAVE_KB_COLS); cnt++)
            {
                data = (buf[index++]&0xFF);//<<0;
                data = data | (buf[index++]&0xFF)<<8;
                data = data | (buf[index++]&0xFF)<<16;
                slave->direct_rgb[cnt] = data;
            }
            break;
        case RGB_SLAVE_CMD_DIRECT1:   // 直驱
            for(cnt=0; cnt<(RGB_SLAVE_KB_ROWS*RGB_SLAVE_KB_COLS)/3; cnt++)
            {
                data = (buf[index++]&0xFF);//<<0;
                data = data | (buf[index++]&0xFF)<<8;
                data = data | (buf[index++]&0xFF)<<16;
                slave->direct_rgb[cnt+0*RGB_SLAVE_KB_COLS] = data;
            }
            break;
        case RGB_SLAVE_CMD_DIRECT2:   // 直驱
            for(cnt=0; cnt<(RGB_SLAVE_KB_ROWS*RGB_SLAVE_KB_COLS)/3; cnt++)
            {
                data = (buf[index++]&0xFF);//<<0;
                data = data | (buf[index++]&0xFF)<<8;
                data = data | (buf[index++]&0xFF)<<16;
                slave->direct_rgb[cnt+2*RGB_SLAVE_KB_COLS] = data;
            }
            break;
        case RGB_SLAVE_CMD_DIRECT3:   // 直驱
        /*
        数据包格式
        | 0x5C | 0x05|126B |~0x5C| 129B
        | head | cmd | rgb | end |
        */
            //slave->transfer.offset = buf[index++];
            //for(cnt=0; cnt<sizeof(slave->direct_sub.rgb); cnt++) slave->direct_sub.rgb[cnt] = buf[index++];
            for(cnt=0; cnt<(RGB_SLAVE_KB_ROWS*RGB_SLAVE_KB_COLS)/3; cnt++)
            {
                data = (buf[index++]&0xFF);//<<0;
                data = data | (buf[index++]&0xFF)<<8;
                data = data | (buf[index++]&0xFF)<<16;
                slave->direct_rgb[cnt+4*RGB_SLAVE_KB_COLS] = data;
            }
            break;
            break;
        case RGB_SLAVE_CMD_READ:
            //slave->read.offset = buf[index++];
            break;
        case RGB_SLAVE_CMD_TEST:
        /*
        数据包格式
        | 0x5C | 0x07|  1B |  1B |  1B    |  1B  |  4B  |  24B |  4B   |~0x5C| 39B
        | head | cmd | col | row | IdxLogo| RevX | RevY | masks| color | end |
        */
            slave->test.col = buf[index++];
            slave->test.row = buf[index++];
            slave->test.IdxLogo = buf[index++];
            slave->test.reverseX = buf[index++];
            data = (buf[index++]&0xFF);//<<0;
            data = data | (buf[index++]&0xFF)<<8;
            data = data | (buf[index++]&0xFF)<<16;
            data = data | (buf[index++]&0xFF)<<24;
            slave->test.reverseY = data;
            for(cnt=0; cnt<RGB_SLAVE_KB_ROWS; cnt++)
            {
                data = (buf[index++]&0xFF);//<<0;
                data = data | (buf[index++]&0xFF)<<8;
                data = data | (buf[index++]&0xFF)<<16;
                data = data | (buf[index++]&0xFF)<<24;
                slave->test.masks[cnt] = data;
            }
            {
                data = (buf[index++]&0xFF);//<<0;
                data = data | (buf[index++]&0xFF)<<8;
                data = data | (buf[index++]&0xFF)<<16;
                data = data | (buf[index++]&0xFF)<<24;
                slave->test.color = data;
            }
            break;
		default:
			break;
	}
    if(((~RGB_SLAVE_HEAD)&0xFF)!= buf[index++] ) return -2;
	slave->end = ~RGB_SLAVE_HEAD; // end
    if(index>len) return -3;  // over
	return index;
}
// 通用包校验函数,对数据包进行校验,并返回正常校验的数据长度
int rgb_slave_check(const uint8_t buf[384], const uint16_t len)
{
    int index=0;
    uint8_t head;   // 0x5C
    uint8_t cmd;
    head = buf[index++];
    if(RGB_SLAVE_HEAD!=head) return -1;
    cmd = buf[index++];
    switch(cmd)
    {
        case RGB_SLAVE_CMD_ACK:
        /*
        数据包格式
        | 0x5C | 0xFF|  1B  |  1B  |  1B   |~0x5C| 6B
        | head | cmd | _cmd | code | check | end |
        */
            index +=3;
            break;
        case RGB_SLAVE_CMD_SLEEP:
            break;
        case RGB_SLAVE_CMD_INIT:
        /*
        数据包格式
        | 0x5C | 0x01|  21  |  6   |  1B    |  1B  |  4B  |  24B |   32B   |~0x5C| 67B
        | head | cmd | cols | rows | IdxLogo| RevX | RevY | masks| palettes| end |
        */
            index = index + (1+1+1+1+4+24+32);
            break;
        case RGB_SLAVE_CMD_CTRL:
        /*
        数据包格式
        | 0x5C | 0x02|  1B  |  1B   | 1B  |  4B  |  4B  |  24B |  1B  |~0x5C| 39B
        | head | cmd | Mode | Speed | Rev | back | logo | keys | norm | end |
        */
            index = index + (1+1+1+1+4+4+24+1);
            break;
        case RGB_SLAVE_CMD_UDEF:
        case RGB_SLAVE_CMD_RECORD:
        /*
        数据包格式
        | 0x5C | 0x03|126B |~0x5C| 129B
        | head | cmd | rgb | end |
        0x03:自定义(调色板中颜色索引0-6);
        0x04:自定义录制(调色板中颜色索引0-6);
        */
            index = index + (RGB_SLAVE_KB_ROWS*RGB_SLAVE_KB_COLS);
            break;
        case RGB_SLAVE_CMD_DIRECT:   // 直驱
        /*
        数据包格式
        | 0x5C | 0x05|378B |~0x5C| 381B
        | head | cmd | rgb | end |
        */
            index = index + (3*RGB_SLAVE_KB_ROWS*RGB_SLAVE_KB_COLS);
            break;
        case RGB_SLAVE_CMD_DIRECT1:   // 直驱
        case RGB_SLAVE_CMD_DIRECT2:   // 直驱
        case RGB_SLAVE_CMD_DIRECT3:   // 直驱
        /*
        数据包格式
        | 0x5C | 0x05|126B |~0x5C| 129B
        | head | cmd | rgb | end |
        */
            index = index + (3*RGB_SLAVE_KB_ROWS/3*RGB_SLAVE_KB_COLS);
            break;
        case RGB_SLAVE_CMD_READ:
            break;
        case RGB_SLAVE_CMD_TEST:
        /*
        数据包格式
        | 0x5C | 0x07|  1B |  1B |  1B    |  1B  |  4B  |  24B |  4B   |~0x5C| 39B
        | head | cmd | col | row | IdxLogo| RevX | RevY | masks| color | end |
        */
            index = index + (1+1+1+1+4+24+4);
            break;
        default:
            break;
    }
    if(((~RGB_SLAVE_HEAD)&0xFF)!= buf[index++] ) return -2;
    if(index>len) return -3;  // over
    return index;
}
